home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / pcmagazi / assemblr / 04 / snapshot.asm < prev    next >
Assembly Source File  |  1986-06-05  |  15KB  |  284 lines

  1. INTERRUPTS      SEGMENT AT 0H   ;This is where the keyboard interrupt
  2.         ORG     9H*4            ;holds the address of its service routine
  3. KEYBOARD_INT    LABEL   DWORD
  4. INTERRUPTS      ENDS
  5.  
  6. SCREEN  SEGMENT AT 0B000H       ;A dummy segment to use as the
  7. SCREEN  ENDS                    ;Extra Segment
  8.  
  9. ROM_BIOS_DATA   SEGMENT AT 40H  ;BIOS statuses held here, also keyboard buffer
  10.  
  11.         ORG     1AH
  12.         HEAD DW      ?                  ;Unread chars go from Head to Tail
  13.         TAIL DW      ?
  14.         BUFFER       DW      16 DUP (?)         ;The buffer itself
  15.         BUFFER_END   LABEL   WORD
  16.  
  17. ROM_BIOS_DATA   ENDS
  18.  
  19. CODE_SEG        SEGMENT
  20.         ASSUME  CS:CODE_SEG
  21.         ORG     100H            ;ORG = 100H to make this into a .COM file
  22. FIRST:  JMP     LOAD_SNAPSHOT   ;First time through jump to initialize routine
  23.  
  24.         COPY_RIGHT DB  '(C) S. HOLZNER 1985'  ;An Ascii signature
  25. ;        KEYS   DW   310EH,2106H,1E01H,3002H,2E03H ;A Sample: ^N,^F,^A,^B,^C
  26.         KEYS   DW   5 DUP(0)
  27.         FLASHED    DB      0               ;Have we flashed a screenful? 1=yes
  28.         SNAPSHOT_OFFSET      DW      0          ;Chooses 1st 250 bytes or 2nd
  29.         SCREEN_SEG_OFFSET       DW      0       ;0 for mono, 8000H for graphics
  30.         IO_CHAR         DW      ?               ;Holds addr of Put or Get_Char
  31.         FILE_SIZE       DW      0               ;Read in this many bytes
  32.         OLD_KEYBOARD_INT        DD      ?       ;Location of old kbd interrupt
  33.         FILE            DB  'A.DAT',0           ;Asciiz. Changed to B.Dat, etc.
  34.         WS_FLAG         DB      0               ;<-- Set to 1 to strip WordStar
  35.         SNAPSHOT             DB      10000 DUP (32) ;Storage for screens
  36.  
  37. SNAP    PROC    NEAR            ;The keyboard interrupt will now come here.
  38.         ASSUME  CS:CODE_SEG
  39.         PUSH    AX              ;Save the used registers for good form
  40.         PUSH    BX
  41.         PUSH    CX
  42.         PUSH    DX
  43.         PUSH    DI
  44.         PUSH    SI
  45.         PUSH    DS
  46.         PUSH    ES
  47.         PUSHF                   ;First, call old keyboard interrupt
  48.         CALL    OLD_KEYBOARD_INT
  49.  
  50.         ASSUME  DS:ROM_BIOS_DATA        ;Examine the char just put in
  51.         MOV     BX,ROM_BIOS_DATA
  52.         MOV     DS,BX
  53.         MOV     BX,TAIL                 ;Point to current tail
  54.         CMP     BX,HEAD                 ;If at head, kbd int has deleted char
  55.         JE      IN                      ;So leave
  56.         SUB     BX,2                    ;Point to just read in character
  57.         CMP     BX,OFFSET BUFFER        ;Did we undershoot buffer?
  58.         JAE     NO_WRAP                 ;Nope
  59.         MOV     BX,OFFSET BUFFER_END    ;Yes -- move to buffer top
  60.         SUB     BX,2                    ;Point to just read in character
  61. NO_WRAP:MOV     DX,[BX]                 ;** Typed character in DX now **
  62.         LEA     SI,KEYS                 ;Point to Keys for search
  63.         CMP     FLASHED,1               ;Should we restore screen?
  64.         JE      RESTORE                 ;Yes, jump there
  65.         CMP     DX,CS:[SI]              ;Compare to first key (Store screen)
  66.         JE      STORE                   ;So Store
  67.         ADD     SI,2                    ;Point to next key
  68.         CMP     DX,CS:[SI]              ;Second key -- should we flash screen?
  69.         JE      FLASH                   ;Yes
  70.         MOV     CX,3                    ;No -- check for .Dat keys (A.Dat,etc)
  71.         MOV     SNAPSHOT_OFFSET,4000    ;Point to beginning of .Dats in memory
  72. TEST:   ADD     SI,2                    ;Increment to next key
  73.         CMP     DX,CS:[SI]              ;Is it right?
  74.         JE      DATS                    ;Yes, flash a .Dat file on screen
  75.         ADD     SNAPSHOT_OFFSET,2000    ;Point to next .Dat
  76.         LOOP    TEST                    ;And go back until all three are done
  77.         JMP     OUT                     ;No keys matched. Jump Out.
  78. STORE:  MOV     TAIL,BX                 ;Delete character from buffer
  79.         MOV     FLASHED,0               ;Switch Modes on Flashed
  80.         MOV     SNAPSHOT_OFFSET,0       ;Point to screen storage part of pad
  81.         LEA     AX,GET_CHAR             ;Make IO use Get_char so current screen
  82.         MOV     IO_CHAR,AX              ;is stored
  83.         CALL    IO                      ;Store Screen
  84. IN:     JMP     OUT                     ;Done here, let's go.
  85. FLASH:  MOV     TAIL,BX
  86.         MOV     FLASHED,1           ;Switch Modes, next key will restore screen
  87.         MOV     SNAPSHOT_OFFSET,2000    ;Point to screen storage part
  88.         LEA     AX,GET_CHAR             ;Make IO use Get_char so current screen
  89.         MOV     IO_CHAR,AX              ;is stored
  90.         CALL    IO                      ;Store Screen
  91.         MOV     SNAPSHOT_OFFSET,0       ;Use 1st 250 bytes of Snapshot memory
  92.         LEA     AX,PUT_CHAR             ;Make IO use Put-Char so it does
  93.         MOV     IO_CHAR,AX
  94.         CALL    IO                      ;Put result on screen
  95.         JMP     OUT                     ;Done here.
  96. RESTORE:
  97.         MOV     FLASHED,0               ;Restore screen from memory
  98.         MOV     TAIL,BX                 ;Delete character from buffer
  99.         MOV     SNAPSHOT_OFFSET,2000    ;Point to storage part of memory
  100.         LEA     AX,PUT_CHAR             ;Make IO call Put_Char as it scans
  101.         MOV     IO_CHAR,AX              ;over all locations in screen
  102.         CALL    IO                      ;Restore screen
  103.         JMP     OUT                     ;And leave
  104.  
  105. DATS:   MOV     TAIL,BX
  106.         MOV     FLASHED,1           ;Switch Modes, next key will restore screen
  107.         PUSH    SNAPSHOT_OFFSET         ;Save this while Offset set for storing
  108.         MOV     SNAPSHOT_OFFSET,2000    ;Point to screen storage part
  109.         LEA     AX,GET_CHAR             ;Make IO use Get_char so current screen
  110.         MOV     IO_CHAR,AX              ;is stored
  111.         CALL    IO                      ;Store Screen
  112.         POP     SNAPSHOT_OFFSET         ;Restore pointer to stored .Dat
  113.         LEA     AX,PUT_CHAR             ;Make IO use Put-Char so it does
  114.         MOV     IO_CHAR,AX
  115.         CALL    IO                      ;Put result on screen
  116.  
  117. OUT:    POP     ES                      ;Do the Pops of all registers.
  118.         POP     DS
  119.         POP     SI
  120.         POP     DI
  121.         POP     DX
  122.         POP     CX
  123.         POP     BX
  124.         POP     AX
  125.         IRET                    ;An interrupt needs an IRET
  126. SNAP    ENDP
  127.  
  128. GET_CHAR        PROC    NEAR    ;Gets a char from screen and advances position
  129.         PUSH    DX
  130.         MOV     SI,2            ;Loop twice, once for char, once for attribute
  131. G_WAIT_LOW:
  132.         MOV     AH,ES:[DI]      ;Do the move from the screen, one byte at a time
  133.         INC     DI              ;Move to next screen location
  134.         DEC     SI              ;Decrement loop counter
  135.         CMP     SI,0            ;Are we done?
  136.         JE      LEAVE           ;Yes
  137.         MOV     SNAPSHOT[BX],AH      ;No -- put char we got into snapshot
  138.         JMP     G_WAIT_LOW      ;Do it again
  139. LEAVE:  INC     BX              ;Update location
  140.         POP     DX
  141.         RET
  142. GET_CHAR        ENDP
  143.  
  144. PUT_CHAR        PROC    NEAR    ;Puts one char on screen and advances position
  145.         PUSH    DX
  146.         MOV     AH,SNAPSHOT[BX]      ;Get the char to be put onto the screen
  147.         MOV     SI,2            ;Loop twice, once for char, once for attribute
  148.         MOV     ES:[DI],AH      ;Move to screen, one byte at a time
  149.         ADD     DI,2
  150.         SUB     SI,2
  151.         INC     BX              ;Point to next char
  152.         POP     DX
  153.         RET                     ;Exeunt
  154. PUT_CHAR        ENDP
  155.  
  156. IO      PROC    NEAR           ;This scans over all screen positions
  157.         ASSUME  ES:SCREEN               ;Use screen as extra segment
  158.         MOV     BX,SCREEN
  159.         MOV     ES,BX
  160.  
  161.         MOV     DI,SCREEN_SEG_OFFSET    ;DI will be pointer to screen postion
  162.         MOV     BX,SNAPSHOT_OFFSET           ;BX will be location pointer
  163.         MOV     CX,25                   ;There will be 10 lines
  164. LINE_LOOP:
  165.         MOV     DX,80                   ;And 25 spaces across
  166. CHAR_LOOP:
  167.         CALL    IO_CHAR                 ;Call Put-Char or Get-Char
  168.         DEC     DX                      ;Decrement character loop counter
  169.         JNZ     CHAR_LOOP               ;If not zero, scan over next character
  170.         LOOP    LINE_LOOP               ;And now go back to do next line
  171.         RET                             ;Finished
  172. IO      ENDP
  173.  
  174. READ_FILE       PROC    NEAR            ;Reads .Dats and formats in memory.
  175.         PUSH    CX                      ;Save used registers
  176.         PUSH    DX
  177.         PUSH    DI
  178.         ASSUME  DS:CODE_SEG,ES:CODE_SEG
  179.         MOV     BX,AX                   ;Put passed file handle in BX
  180.         MOV     CX,2000                 ;Ask for 2000 bytes (Tops)
  181.         LEA     DX,DATA                 ;Point DS:DX at Data area at end
  182.         MOV     AH,3FH                  ;Ask for reading service
  183.         INT     21H                     ;And go get 'em
  184.         MOV     CX,AX                   ;Store number of bytes read
  185.         MOV     AH,3EH                  ;Now close file
  186.         INT     21H
  187.         CALL    WS                      ;Strip high bit if necessary
  188.         LEA     SI,DATA                 ;Transfer from CS:[SI] to DS:[BX] now
  189.         CMP     CX,2000                 ;Make sure on number of bytes read in.
  190.         JBE     THE_LOOP
  191.         MOV     CX,2000                 ;Format file into Snapshot area now
  192. THE_LOOP:                               ;Loop over character by character
  193.         CMP     BYTE PTR [SI],9         ;Is it a tab?
  194.         JNE     NOTAB                   ;Add 8 spaces for tabs
  195.         ADD     DI,8
  196.         INC     SI                      ;And point to next character
  197.         JMP     CONT
  198. NOTAB:  CMP     BYTE PTR [SI],13        ;Is it a carriage return?
  199.         JNE     OK                      ;No, store the character
  200. FILL:   INC     SI                      ;Found a <CR>. Fill to end of line
  201.         DEC     CX                      ;Get rid of line feeds
  202.         CMP     BYTE PTR [SI],13        ;Treat additional <CR>s as new lines
  203.         JE      CR
  204.         CMP     BYTE PTR [SI],' '       ;Bona Fide character?
  205.         JB      FILL                    ;No, keep going past all linefeeds
  206. CR:     CMP     CX,0                    ;Yes, start to fill to end of line here
  207.         JLE     FIN                     ;Check on loop index
  208.         INC     CX                      ;And readjust it from skipping lf.s
  209.         MOV     AX,DI                   ;AH will check if we're at end of line
  210.         SUB     AX,OFFSET SNAPSHOT+4000 ;Get distance into screen
  211.         MOV     DL,80                   ;Divide by 80 to find columns
  212.         DIV     DL
  213. CHECK:  CMP     AH,79                   ;Remainder of 79?
  214.         JA      CONT                    ;If more, have begun a new line.
  215. ADD:    INC     DI                      ;Add a space by incrementing DI
  216.         INC     AH                      ;And keep track by incrementing AH too.
  217.         JMP     CHECK                   ;At edge of screen?
  218. OK:     CMP     DI,OFFSET SNAP    ;Past end of storage area? (Many tabs and CRs)
  219.         JAE     FIN                     ;Yes, don't move byte into it
  220.         MOVSB                           ;No, safe to move byte from [SI] to [DI]
  221. CONT:   LOOP    THE_LOOP                ;And keep going for all bytes in file
  222. FIN:    POP     DI
  223.         POP     DX
  224.         POP     CX
  225.         RET                             ;Exit here.
  226. READ_FILE       ENDP
  227.  
  228. WS      PROC    NEAR                    ;This will strip high bits from the
  229.         CMP     WS_FLAG,1               ;  read-in file if WS_Flag = 1
  230.         JNE     RETWS                   ;IF WS_Flag is not 1, exit
  231.         PUSH    SI                      ;Store used registers
  232.         PUSH    CX
  233.         LEA     SI,DATA                 ;Point to read-in file
  234.         MOV     CX,2000                 ;Do 2000 bytes
  235. ALOOP:  AND     BYTE PTR CS:[SI],127    ;Strip top bit
  236.         INC     SI                      ;Point to next one.
  237.         LOOP    ALOOP                   ;And keep going
  238.         POP     CX                      ;Pops
  239.         POP     SI
  240. RETWS:  RET                             ;And Exit.
  241. WS      ENDP
  242.  
  243. LOAD_SNAPSHOT        PROC    NEAR    ;This procedure intializes everything
  244.         ASSUME  DS:INTERRUPTS   ;The data segment will be the Interrupt area
  245.         MOV     AX,INTERRUPTS
  246.         MOV     DS,AX
  247.  
  248.         MOV     AX,word ptr KEYBOARD_INT ;Get the old interrupt service routine
  249.         MOV     word ptr OLD_KEYBOARD_INT,AX ;address, put it into our location
  250.         MOV     AX,word ptr KEYBOARD_INT[2] ;OLD_KEYBOARD_INT so we can call it.
  251.         MOV     word ptr OLD_KEYBOARD_INT[2],AX
  252.  
  253.         MOV     word ptr KEYBOARD_INT,OFFSET SNAP ;Load address of our program
  254.         MOV     word ptr KEYBOARD_INT[2],CS   ;routine into the keyboard interrupt
  255.         MOV     AH,15                   ;Ask for service 15 of INT 10H
  256.         INT     10H                     ;This tells us how display is set up
  257.         TEST    AL,4                    ;Is it?
  258.         JNZ     READ                    ;Yes - jump out
  259.         MOV     SCREEN_SEG_OFFSET,8000H ;No - set up for graphics display
  260. READ:   PUSH    CS                      ;Now read in A.Dat, B.Dat etc.
  261.         POP     DS                      ;Set DS correctly
  262.         MOV     CX,3                    ;Loop over three files
  263.         LEA     DI,SNAPSHOT+4000        ;Store starting in this area
  264. LOOP:   ASSUME  DS:CODE_SEG             ;Loop over files
  265.         LEA     DX,FILE                 ;Point to file name
  266.         MOV     AX,3D00H                ;Service 3DH, attribute 0 for file
  267.         INT     21H                     ;Open file
  268.         JC      EXIT                    ;If not found, exit
  269. ;       PUSH    DI                      ;Store
  270.         CALL    READ_FILE               ;Pass file handle in AX to Read_File
  271. ;       POP     DI
  272.         ADD     DI,2000                 ;Point to next storage area
  273.         MOV     BX,DX                   ;Change A.Dat into B.Dat etc.
  274.         INC     BYTE PTR CS:[BX]        ;A.DAT-->B.DAT etc.
  275.         LOOP    LOOP                    ;Keep going over all files.
  276. EXIT:   MOV     DX,OFFSET LOAD_SNAPSHOT ;Set up everything but LOAD_SNAPSHOT to
  277.         INT     27H                     ;stay and attach itself to DOS
  278. LOAD_SNAPSHOT        ENDP
  279. DATA:
  280.         CODE_SEG        ENDS
  281.  
  282.         END     FIRST   ;END "FIRST" so 8088 will go to FIRST first.
  283.  
  284.